Expand description
RustCrypto: RSA
A portable RSA implementation in pure Rust.
Example
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
let mut rng = rand::thread_rng();
let bits = 2048;
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pub_key = RsaPublicKey::from(&priv_key);
// Encrypt
let data = b"hello world";
let enc_data = pub_key.encrypt(&mut rng, Pkcs1v15Encrypt, &data[..]).expect("failed to encrypt");
assert_ne!(&data[..], &enc_data[..]);
// Decrypt
let dec_data = priv_key.decrypt(Pkcs1v15Encrypt, &enc_data).expect("failed to decrypt");
assert_eq!(&data[..], &dec_data[..]);
Note: If you encounter unusually slow key generation time while using
RsaPrivateKey::new
you can try to compile in release mode or add the following to yourCargo.toml
. Key generation is much faster when building with higher optimization levels, but this will increase the compile time a bit.[profile.debug] opt-level = 3
If you don’t want to turn on optimizations for all dependencies, you can only optimize the
num-bigint-dig
dependency. This should give most of the speedups.[profile.dev.package.num-bigint-dig] opt-level = 3
Status
Currently at Phase 1 (v) 🚧
There will be three phases before 1.0
🚢 can be released.
- 🚧 Make it work
- Prime generation ✅
- Key generation ✅
- PKCS1v1.5: Encryption & Decryption ✅
- PKCS1v1.5: Sign & Verify ✅
- PKCS1v1.5 (session key): Encryption & Decryption
- OAEP: Encryption & Decryption
- PSS: Sign & Verify
- Key import & export
- 🚀 Make it fast
- Benchmarks ✅
- compare to other implementations 🚧
- optimize 🚧
- 🔐 Make it secure
- Fuzz testing
- Security Audits
⚠️Security Warning
This crate has received one security audit by Include Security, with only one minor finding which has since been addressed.
See the open security issues on our issue tracker for other known problems.
Notably the implementation of modular exponentiation is not constant time,
but timing variability is masked using random blinding, a commonly used
technique. This crate is vulnerable to the Marvin Attack which could enable
private key recovery by a network attacker (see RUSTSEC-2023-0071).
You can follow our work on mitigating this issue in #390.
Minimum Supported Rust Version (MSRV)
All crates in this repository support Rust 1.65 or higher.
In the future MSRV can be changed, but it will be done with a minor version bump.
License
Licensed under either of
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Supported algorithms
This crate supports several schemes described in RFC8017:
- OAEP encryption scheme
- PKCS#1 v1.5 encryption scheme
- PKCS#1 v1.5 signature scheme
- PSS signature scheme
These schemes are described below.
Usage
OAEP encryption
Note: requires sha2
feature of rsa
crate is enabled.
use rsa::{RsaPrivateKey, RsaPublicKey, Oaep, sha2::Sha256};
let mut rng = rand::thread_rng();
let bits = 2048;
let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let public_key = RsaPublicKey::from(&private_key);
// Encrypt
let data = b"hello world";
let padding = Oaep::new::<Sha256>();
let enc_data = public_key.encrypt(&mut rng, padding, &data[..]).expect("failed to encrypt");
assert_ne!(&data[..], &enc_data[..]);
// Decrypt
let padding = Oaep::new::<Sha256>();
let dec_data = private_key.decrypt(padding, &enc_data).expect("failed to decrypt");
assert_eq!(&data[..], &dec_data[..]);
PKCS#1 v1.5 encryption
use rsa::{RsaPrivateKey, RsaPublicKey, Pkcs1v15Encrypt};
let mut rng = rand::thread_rng();
let bits = 2048;
let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let public_key = RsaPublicKey::from(&private_key);
// Encrypt
let data = b"hello world";
let enc_data = public_key.encrypt(&mut rng, Pkcs1v15Encrypt, &data[..]).expect("failed to encrypt");
assert_ne!(&data[..], &enc_data[..]);
// Decrypt
let dec_data = private_key.decrypt(Pkcs1v15Encrypt, &enc_data).expect("failed to decrypt");
assert_eq!(&data[..], &dec_data[..]);
PKCS#1 v1.5 signatures
Note: requires sha2
feature of rsa
crate is enabled.
use rsa::RsaPrivateKey;
use rsa::pkcs1v15::{SigningKey, VerifyingKey};
use rsa::signature::{Keypair, RandomizedSigner, SignatureEncoding, Verifier};
use rsa::sha2::{Digest, Sha256};
let mut rng = rand::thread_rng();
let bits = 2048;
let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let signing_key = SigningKey::<Sha256>::new(private_key);
let verifying_key = signing_key.verifying_key();
// Sign
let data = b"hello world";
let signature = signing_key.sign_with_rng(&mut rng, data);
assert_ne!(signature.to_bytes().as_ref(), data.as_slice());
// Verify
verifying_key.verify(data, &signature).expect("failed to verify");
PSS signatures
Note: requires sha2
feature of rsa
crate is enabled.
use rsa::RsaPrivateKey;
use rsa::pss::{BlindedSigningKey, VerifyingKey};
use rsa::signature::{Keypair,RandomizedSigner, SignatureEncoding, Verifier};
use rsa::sha2::{Digest, Sha256};
let mut rng = rand::thread_rng();
let bits = 2048;
let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let signing_key = BlindedSigningKey::<Sha256>::new(private_key);
let verifying_key = signing_key.verifying_key();
// Sign
let data = b"hello world";
let signature = signing_key.sign_with_rng(&mut rng, data);
assert_ne!(signature.to_bytes().as_ref(), data);
// Verify
verifying_key.verify(data, &signature).expect("failed to verify");
PKCS#1 RSA Key Encoding
PKCS#1 supports a legacy format for encoding RSA keys as binary (DER) or text (PEM) data.
You can recognize PEM encoded PKCS#1 keys because they have “RSA * KEY” in the type label, e.g.:
-----BEGIN RSA PRIVATE KEY-----
Most modern applications use the newer PKCS#8 format instead (see below).
The following traits can be used to decode/encode RsaPrivateKey
and
RsaPublicKey
as PKCS#1. Note that pkcs1
is re-exported from the
toplevel of the rsa
crate:
pkcs1::DecodeRsaPrivateKey
: decode RSA private keys from PKCS#1pkcs1::EncodeRsaPrivateKey
: encode RSA private keys to PKCS#1pkcs1::DecodeRsaPublicKey
: decode RSA public keys from PKCS#1pkcs1::EncodeRsaPublicKey
: encode RSA public keys to PKCS#1
Example
use rsa::{RsaPublicKey, pkcs1::DecodeRsaPublicKey};
let pem = "-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAtsQsUV8QpqrygsY+2+JCQ6Fw8/omM71IM2N/R8pPbzbgOl0p78MZ
GsgPOQ2HSznjD0FPzsH8oO2B5Uftws04LHb2HJAYlz25+lN5cqfHAfa3fgmC38Ff
wBkn7l582UtPWZ/wcBOnyCgb3yLcvJrXyrt8QxHJgvWO23ITrUVYszImbXQ67YGS
0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0NfFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J
9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejIn04APPKIjpMyQdnWlby7rNyQtE4+CV+j
cFjqJbE/Xilcvqxt6DirjFCvYeKYl1uHLwIDAQAB
-----END RSA PUBLIC KEY-----";
let public_key = RsaPublicKey::from_pkcs1_pem(pem)?;
PKCS#8 RSA Key Encoding
PKCS#8 is a private key format with support for multiple algorithms. Like PKCS#1, it can be encoded as binary (DER) or text (PEM).
You can recognize PEM encoded PKCS#8 keys because they don’t have an algorithm name in the type label, e.g.:
-----BEGIN PRIVATE KEY-----
The following traits can be used to decode/encode RsaPrivateKey
and
RsaPublicKey
as PKCS#8. Note that pkcs8
is re-exported from the
toplevel of the rsa
crate:
pkcs8::DecodePrivateKey
: decode private keys from PKCS#8pkcs8::EncodePrivateKey
: encode private keys to PKCS#8pkcs8::DecodePublicKey
: decode public keys from PKCS#8pkcs8::EncodePublicKey
: encode public keys to PKCS#8
Example
use rsa::{RsaPublicKey, pkcs8::DecodePublicKey};
let pem = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtsQsUV8QpqrygsY+2+JC
Q6Fw8/omM71IM2N/R8pPbzbgOl0p78MZGsgPOQ2HSznjD0FPzsH8oO2B5Uftws04
LHb2HJAYlz25+lN5cqfHAfa3fgmC38FfwBkn7l582UtPWZ/wcBOnyCgb3yLcvJrX
yrt8QxHJgvWO23ITrUVYszImbXQ67YGS0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0N
fFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejI
n04APPKIjpMyQdnWlby7rNyQtE4+CV+jcFjqJbE/Xilcvqxt6DirjFCvYeKYl1uH
LwIDAQAB
-----END PUBLIC KEY-----";
let public_key = RsaPublicKey::from_public_key_pem(pem)?;
Re-exports
pub use crate::errors::Error;
pub use crate::errors::Result;
pub use crate::oaep::Oaep;
pub use crate::pkcs1v15::Pkcs1v15Encrypt;
pub use crate::pkcs1v15::Pkcs1v15Sign;
pub use crate::pss::Pss;
pub use rand_core;
pub use signature;
pub use pkcs1;
pub use pkcs8;
pub use sha2;
Modules
- Error types.
- hazmat
hazmat
⚠️ Low-level “hazmat” RSA functions. - Encryption and Decryption using OAEP padding.
- PKCS#1 v1.5 support as described in RFC8017 § 8.2.
- Support for the Probabilistic Signature Scheme (PSS) a.k.a. RSASSA-PSS.
- RSA-related trait definitions.
Structs
- A big unsigned integer type.
- Contains the precomputed Chinese remainder theorem values.
- Represents a whole RSA key, public and private parts.
- Represents the public part of an RSA key.